package face.pay.api.payter.channel.paytype.wechat;

import com.alibaba.fastjson.JSONObject;
import com.face.pay.WxApiConfig;
import com.github.wxpay.sdk.WXPayRequest;
import com.github.wxpay.sdk.WXPayUtil;
import face.pay.api.payter.channel.paytype.message.MessageSender;
import face.pay.api.wechat.param.PayParam;
import face.pay.constant.OrderType;
import face.pay.constant.PayType;
import face.pay.entity.EnterpriseInfo;
import face.pay.entity.OemInfo;
import face.pay.entity.OrderInfo;
import face.pay.entity.StoreInfo;
import face.pay.api.payter.channel.paytype.AbstractPayType;
import face.pay.util.IpUtils;
import face.pay.util.ResultMessage;
import face.pay.util.bean.JavaBeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

/**
 * 微信刷脸支付
 */
@Component
@Slf4j
public class WxFacePay extends AbstractPayType {

    private final static   String domain    = "api.mch.weixin.qq.com";

    private final static   String urlSuffix = "/pay/facepay";

    @Autowired
    private MessageSender profitSender;

    /**
     * 微信刷脸支付
     * @param json
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultMessage pay(JSONObject json) {

        log.info("微信刷脸支付JSON" + json.toString());

        try{
            PayParam payParam = json.toJavaObject(PayParam.class);

            String openid = payParam.getOpenid();
            String out_trade_no = payParam.getOut_trade_no();
            String channelCode = json.getString("channelCode");

            Long total_fee = payParam.getTotal_fee() == null ? new Integer(0) : payParam.getTotal_fee();

            Long actFee =  total_fee;

            Integer terminalId = json.getInteger("terminalId");

            Long orderId = Long.valueOf(out_trade_no);
            log.info("查找订单: orderId" + orderId);

            OrderInfo orderInfo = this.orderInfoDao.getById(orderId);

            if (orderInfo != null) {

                if (!new Integer(0).equals(orderInfo.getStatus())) {
                    log.info("订单已经被处理，重新发起支付请求 ");

                    return ResultMessage.createFail("订单已经被处理，重新发起支付请求");
                }

                Boolean safe = this.paySafe(orderInfo, terminalId, total_fee);
                if (!safe) {
                    log.info("交易信息不正确，中断支付");
                    return ResultMessage.createFail("交易信息不正确，中断支付");
                }else {
                    Integer oemId = orderInfo.getOemId();

                    WxApiConfig wxApiConfig = this.iWxPayConfigServer.getConfig(oemId);
                    if (wxApiConfig.validate()) {

                        WXPayRequest wxPayRequest = new WXPayRequest(wxApiConfig);

                        Integer storeId = orderInfo.getStoreId();

                        OemInfo oemInfo = this.oemInfoDao.getOemInfoById(oemId);

                        String type = oemInfo.getType();

                        StoreInfo storeInfo = this.storeInfoDao.getById(storeId);

                        EnterpriseInfo enterpriseInfo = this.enterpriseInfoDao.getById(storeInfo.getEnterpriseId());

                        String appId = wxApiConfig.getAppID();
                        String apiKey = wxApiConfig.getKey();
                        String mchId = wxApiConfig.getMchID();

                        String subMchId = enterpriseInfo.getWxSubMchId();

                        if (StringUtils.isBlank(subMchId)) {
                            log.info("商家商户号错误");
                            return ResultMessage.createFail("商家商户号错误");
                        }

                        payParam.setAppid(appId);
                        payParam.setMch_id(mchId);
                        payParam.setSub_mch_id(subMchId);

                        String body = storeInfo.getName() + "-线下支付";
                        String ip = IpUtils.getIpAddress();

                        payParam.setSpbill_create_ip(ip);
                        payParam.setBody(body);
                        String nonce_str = WXPayUtil.generateNonceStr();

                        payParam.setNonce_str(nonce_str);
                        Map<String, String> map = JavaBeanUtils.toMap(payParam);

                        map.put("face_code", payParam.getFace_code());
                        map.put("openid",payParam.getOpenid());

                        String xml = WXPayUtil.generateSignedXml(map, apiKey);
                        log.info("刷脸支付 推送到微信服务器消息xml" + xml);


                        String result = wxPayRequest.requestOnce(domain, urlSuffix, xml, false);
                        log.info("返回结果 " + result);

                        Map<String, String> resultMap = WXPayUtil.xmlToMap(result);

                        String return_code = resultMap.get("return_code");

                        if ("SUCCESS".equals(return_code)) {
                            String result_code = resultMap.get("result_code");

                            if ("SUCCESS".equals(result_code)) {

                                resultMap.put("out_trade_no", out_trade_no);
                                resultMap.put("act_fee", String.valueOf(actFee));

                                /**
                                 * 支付成功
                                 */
                                String trade_no = resultMap.get("transaction_id");

                                orderInfo.setType(OrderType.WECHAT);
                                orderInfo.setChannelCode(channelCode);

                                orderInfo.setSharing(0);
                                orderInfo.setScene(0);
                                orderInfo.setActFee(total_fee);
                                orderInfo.setServiceFee(new Long(0));
                                orderInfo.setActInnerFee(actFee);

                                orderInfo.setPayType(PayType.FACE);
                                orderInfo.setStatus(1);
                                orderInfo.setPayCode(payParam.getFace_code());

                                orderInfo.setProfitSign(0);
                                orderInfo.setMessage("支付成功");
                                orderInfo.setPayUserSign(openid);
                                orderInfo.setTradeNo(trade_no);
                                this.orderInfoDao.updatePayInfo(orderInfo);


                                Map<String,String> dataMap =  new HashMap<>();

                                dataMap.put("return_code","SUCCESS");
                                dataMap.put("result_code","SUCCESS");
                                dataMap.put("type",OrderType.WECHAT);
                                dataMap.put("payType",PayType.FACE);
                                dataMap.put("out_trade_no",out_trade_no);
                                dataMap.put("act_fee", String.valueOf(actFee));
                                dataMap.put("total_fee", String.valueOf(total_fee));
                                /**
                                 *
                                 * 调用服务
                                 * 1 判断是都是否是第一次绑定
                                 */
                                ResultMessage resultMessage = ResultMessage.createSuccess(resultMap);

                                this.profitSender.sendMessage(orderInfo,type);

                                log.info("订单支付成功:返回设备请求");
                                return resultMessage;

                            } else {
                                String error = resultMap.get("err_code_des");
                                log.info("订单支付失败:" + error);
                                return ResultMessage.createFail(error);
                            }

                        } else {
                            String error = resultMap.get("return_msg");
                            log.info("订单支付失败:" + error);
                            return ResultMessage.createFail(error);
                        }

                    } else {
                        log.info("商家微信配置错误");
                        return ResultMessage.createFail("商家微信配置错误");
                    }
                }
            }else {
                log.info("订单不存在或订单已失效");
                return ResultMessage.createFail("订单不存在或订单已失效");
            }
        }catch (Exception e){
            log.error("支付异常",e);
        }

        return ResultMessage.createFail("支付失败");
    }


}
